home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
editors
/
ae92.zoo
/
eaea.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-27
|
13KB
|
711 lines
----eaea.c----
/*
* ae.c Anthony's Editor May '92
*
* Public Domain 1991, 1992 by Anthony Howe. All rights released.
*/
#include <ctype.h>
#include <curses.h>
#include <stdio.h>
#include <string.h>
#ifndef BUF
#define BUF 32767
#endif /* BUF */
#ifndef HUP
#define HUP "ae.hup"
#endif /* HUP */
#define HELP_LINE 7
typedef struct keytable_t {
int key;
void (*func)();
} keytable_t;
int done;
int row, col;
int point, page, epage;
int input;
int helpline;
char buf[BUF];
char *ebuf;
char *gap = buf;
char *egap;
char *filename;
keytable_t *table;
/*
* The following assertions must be maintained.
*
* o buf <= gap <= egap <= ebuf
* If gap == egap then the buffer is full.
*
* o cursor = ptr(point) and cursor < gap or egap <= cursor
*
* o page <= point < epage
*
* o 0 <= point <= pos(ebuf) <= BUF
*
*
* Memory representation of the file:
*
* low buf -->+----------+
* | front |
* | of file |
* gap -->+----------+<-- character not in file
* | hole |
* egap -->+----------+<-- character in file
* | back |
* | of file |
* high ebuf -->+----------+<-- character not in file
*
*
* point & gap
*
* The Point is the current cursor position while the Gap is the
* position where the last edit operation took place. The Gap is
* ment to be the cursor but to avoid shuffling characters while
* the cursor moves it is easier to just move a pointer and when
* something serious has to be done then you move the Gap to the
* Point.
*
*
* Use of stdio for portability.
*
* Stdio will handle the necessary conversions of text files to
* and from a machine specific format. Things like fixed length
* records; CRLF mapping into <newline> (\n) and back again;
* null padding; control-Z end-of-file marks; and other assorted
* bizare issues that appear on many unusual machines.
*
* AE is meant to be simple in both code and usage. With that
* in mind certain assumptions are made.
*
* Reading: If a file can not be opened, assume that it is a
* new file. If an error occurs, fall back to a safe state and
* assume an empty file. fread() is typed size_t which is an
* unsigned number. Zero (0) would indicate a read error or an
* empty file. A return value less than BUF is alright, since
* we asked for the maximum allowed.
*
* Writing: If the file can not be opened or a write error occurs,
* then we scramble and save the user's changes in a file called
* ae.hup. If ae.hup fails to open or a write error occurs, then
* we assume that shit happens.
*
*/
int adjust();
int nextline();
int pos();
int prevline();
int save();
char *ptr();
void backsp();
void bottom();
void delete();
void display();
void down();
void file();
void help();
void insert();
void insert_mode();
void left();
void lnbegin();
void lnend();
void movegap();
void pgdown();
void pgup();
void redraw();
void right();
void quit();
void flip();
void top();
void up();
void wleft();
void wright();
#if TERMCAP
/*
* Function Key Support for BSD CURSES.
*
* BSD CURSES does not support function keys as nicely as System V
* or XPG CURSES. So I've provided some functions that can decode
* multi-byte function keys that are commonly supported by BSD's
* termcap file.
*
* The KEY_xxxx macro constants are not defined in the same manner
* as System V or XPG. Also the key_table[] can be customised to
* support additional key sequences that might not be supported by
* termcap. Create a new key code and provide the key sequence
* string; initkey() will not alter the provided sequence provided
* it doesn't match a termcap capability name (see KEY_BACKSPACE).
*/
#include <sys/types.h>
int initkey();
int getkey();
#define KEY_DOWN (-11)
#define KEY_UP (-12)
#define KEY_LEFT (-13)
#define KEY_RIGHT (-14)
#define KEY_BACKSPACE (-15)
#define KEY_DC (-16)
#define KEY_F0 (-20)
#define KEY_F(n) (KEY_F0-(n))
typedef struct key_entry_t {
short code;
char *entry;
} key_entry_t;
char key_buffer[1024];
key_entry_t key_table[] = {
{ KEY_DOWN, "kd" },
{ KEY_UP, "ku" },
{ KEY_LEFT, "kl" },
{ KEY_RIGHT, "kr" },
{ KEY_BACKSPACE, "\b" },
{ KEY_DC, "\177" },
{ KEY_F(0), "k0" },
{ KEY_F(1), "k1" },
{ KEY_F(2), "k2" },
{ KEY_F(3), "k3" },
{ KEY_F(4), "k4" },
{ KEY_F(5), "k5" },
{ KEY_F(6), "k6" },
{ KEY_F(7), "k7" },
{ KEY_F(8), "k8" },
{ KEY_F(9), "k9" },
{ 0, NULL }
};
int
initkey()
{
key_entry_t *k;
char *ptr, *kbuf, *tname;
static char buffer[1024];
if ((tname = (char*) getenv("TERM")) == NULL
|| tgetent(buffer, tname) != 1)
return (0);
for (kbuf = key_buffer, k = key_table; k->entry != NULL; ++k) {
ptr = (char*) tgetstr(k->entry, &kbuf);
if (ptr != NULL)
k->entry = ptr;
}
return (1);
}
int
getkey()
{
key_entry_t *k;
int submatch;
static char buffer[128];
static char *record = buffer;
/* If recorded bytes remain, return next recorded byte. */
if (*record != '\0')
return (*record++);
/* Reset record buffer. */
record = buffer;
do {
/* Read and record one byte. */
*record++ = getch();
*record = '\0';
/* If recorded bytes match any multi-byte sequence... */
for (k = key_table, submatch = 0; k->entry != NULL; ++k) {
char *p, *q;
for (p = buffer, q = k->entry; *p == *q; ++p, ++q) {
if (*p == '\0') {
/* Return extended key code. */
return (k->code);
}
}
if (*p == '\0') {
/* Recorded bytes match anchored substring. */
submatch = 1;
}
}
/* If recorded bytes matched an anchored substring, loop. */
} while (submatch);
/* Return first recorded byte. */
record = buffer;
return (*record++);
}
#else /* not TERMCAP */
#define initkey() keypad(stdscr,1)
#define getkey() getch()
#endif /* TERMCAP */
/* ASCII Control Codes */
#undef CTRL
#define CTRL(x) ((x) & 0x1f)
#define DEL 0x7f
char help_ea[] = "\
Left, right, up, down\tarrow keys\tBeginning and end of line\t^A ^D\n\
Word left and right\t^W ^E\t\tTop and bottom of file\t\t^T ^B\n\
Page up and down\t^P ^N\t\tDelete left and right\tbackspace DEL\n\
Insert\t\t\ttyped keys\tHelp on and off\t\t\tF1\n\
Save file\t\t^F\t\tRedraw\t\t\t\t^R\n\
Quit\t\t\t^C\t\tFlip to VI-style\t\t^Z\n\
....5...10....5...20....5...30....5...40....5...50....5...60....5...70....5...80";
keytable_t modeless[] = {
{ KEY_LEFT, left },
{ KEY_RIGHT, right },
{ KEY_DOWN, down },
{ KEY_UP, up },
{ CTRL('w'), wleft },
{ CTRL('e'), wright },
{ CTRL('n'), pgdown },
{ CTRL('p'), pgup },
{ CTRL('a'), lnbegin },
{ CTRL('d'), lnend },
{ CTRL('t'), top },
{ CTRL('b'), bottom },
{ KEY_BACKSPACE, backsp },
{ '\b', backsp },
{ KEY_DC, delete },
{ DEL, delete },
{ CTRL('f'), file },
{ CTRL('r'), redraw },
{ CTRL('c'), quit },
{ CTRL('z'), flip },
{ KEY_F(1), help },
{ 0, insert }
};
char help_ae[] = "\
Left, right, up, down\th j k l \tBeginning and end of line\t[ ]\n\
Word left and right\tH L\t\tTop and bottom of file\t\tt b\n\
Page up and down\tJ K\t\tDelete left and right\t\tX x\n\
Insert on and off\ti ^L\t\tHelp on and off\t\t\t? \n\
Save file\t\tF\t\tRedraw\t\t\t\tR\n\
Quit\t\t\tQ\t\tFlip to EMACS-style\t\tZ\n\
....5...10....5...20....5...30....5...40....5...50....5...60....5...70....5...80";
keytable_t modual[] = {
{ 'h', left },
{ 'j', down },
{ 'k', up },
{ 'l', right },
{ 'H', wleft },
{ 'J', pgdown },
{ 'K', pgup },
{ 'L', wright },
{ '[', lnbegin },
{ ']', lnend },
{ 't', top },
{ 'b', bottom },
{ 'i', insert_mode },
{ 'x', delete },
{ 'X', backsp },
{ 'F', file },
{ 'R', redraw },
{ 'Q', quit },
{ 'Z', flip },
{ '?', help },
{ 0, movegap }
};
#ifdef POSIX
#include <termios.h>
/*
* Set the desired input mode.
*
* FALSE enables immediate character processing (disable signals
* and line processing.) TRUE enables line processing and signals
* (disables immediate character processing). In either case flow
* control (XON/XOFF) is still active.
*
* If the termios function calls fail, then fall back on using
* CURSES' raw()/noraw() functions; however flow control will be
* affected.
*/
void
lineinput(bf)
int bf;
{
int error;
struct termios term;
error = tcgetatt